/*C风格的不定参函数的使用*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
// fmt格式化字符 ：用户传入的格式字符串，可以包含格式说明符，例如 %d、%s 等，用于打印变量的值
// ...表示可变参数
// ##__VA_ARGS__：允许在调用 LOG 时传入任意数量的额外参数。如果没有可变参数传入，## 会确保宏在展开时不会产生多余的逗号

// 示例：
// fmt 是 "This is a log message: %s\n"，那么最终的字符串在传递给 printf 时会是
// "[%s-%d]This is a log message: %s\n"
// __FILE__ 和 __LINE__ 替换到 %s 和 %d 的位置，再用 __VA_ARGS__ 替换掉 fmt 中的其他格式说明符
#define LOG(fmt, ...) printf("[%s-%d]" fmt , __FILE__, __LINE__, ##__VA_ARGS__)
void printNum(int count, ...)
{
    va_list ap;
    // va_list类似一个指针类型
    va_start(ap, count); // 让ap指向count后第一个可变参数（...中第一个参数）；
    // va_start初始化是让ap 指向第一个可变参数（第一个可变参数的地址）
    for(int i = 0; i < count; i++)
    {
        int n = va_arg(ap, int); // va_arg 逐个获取可变参数(类似遍历)
        // 获取参数: va_arg(ap, type) 从 va_list 变量 ap 中获取一个可变参数（根据指定的类型），并将 ap 更新为指向下一个参数。
        // 需要指定要获取的参数的类型（type），向后移动多少字节
        printf("nums[%d] - %d\n", i, n);
    }
    va_end(ap); // 将ap置空
}

// vasprintf 函数 根据格式字符串和可变数量的参数来生成一个动态分配的字符串；所以使用完之后需要使用free释放空间；
// 否则会造成内存泄露
void myprintf(char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    char *res;
    int ret = vasprintf(&res, fmt, ap); // fmt格式化字符串， ap可变参数列表， res存储完整的字符串
    if(ret != -1) 
    {
        printf(res);
        free(res);
    }
    va_end(ap);
}
int main()
{
    LOG("hello world\n");
    LOG("%s-%d","hello world\n", 666);
    printNum(3, 1, 2, 3);
    printNum(2, 666, 777);
    myprintf("%s - %d", "hahaha", 123456);
    return 0;
}